package fi.foyt.cs.oauth;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.logging.Logger;

import org.json.JSONException;
import org.json.JSONObject;
import org.restlet.data.Form;
import org.restlet.data.Status;
import org.restlet.ext.json.JsonRepresentation;
import org.restlet.representation.EmptyRepresentation;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.resource.Get;
import org.restlet.resource.ResourceException;
import org.restlet.resource.ServerResource;

import com.restfb.DefaultFacebookClient;
import com.restfb.DefaultJsonMapper;
import com.restfb.FacebookClient;
import com.restfb.WebRequestor.Response;
import com.restfb.types.User;
import com.restfb.util.StringUtils;

import fi.foyt.cs.Settings;
import fi.foyt.cs.api.SystemProperty;
import fi.foyt.cs.facebook.GAEWebRequestor;

public class FacebookLogin extends ServerResource {

  @Override
  protected void doInit() throws ResourceException {
    super.doInit();
    log = getLogger();
  }

  @Get("html")
  public Representation represent() {
    StringBuilder returnUrlBuilder = new StringBuilder();
    returnUrlBuilder.append(getReference().getBaseRef());
    returnUrlBuilder.append("?return=true");

    Form query = getQuery();
    boolean returnRequest = "true".equals(query.getFirstValue("return"));

    if (returnRequest) {
      String code = query.getFirstValue("code");

      boolean success = !StringUtils.isBlank(code);
      if (!success) {
        log.info("Authentication Failed");
        getResponse().setStatus(Status.CLIENT_ERROR_NOT_FOUND);
        return new StringRepresentation("Authentication Failed");
      } else {
        StringBuilder accessTokenUrlBuilder;
        try {
          accessTokenUrlBuilder = new StringBuilder("https://graph.facebook.com/oauth/access_token")
            .append("?client_id=")
            .append(URLEncoder.encode(Settings.getValue(SystemProperty.FACEBOOK_APPID), "UTF-8"))
            .append("&client_secret=")
            .append(URLEncoder.encode(Settings.getValue(SystemProperty.FACEBOOK_SECRET), "UTF-8"))
            .append("&code=")
            .append(URLEncoder.encode(code, "UTF-8"))
            .append("&redirect_uri=")
            .append(URLEncoder.encode(returnUrlBuilder.toString(), "UTF-8"));

          GAEWebRequestor webRequestor = new GAEWebRequestor();
          try {
            Response response = webRequestor.executeGet(accessTokenUrlBuilder.toString());
            if (response.getStatusCode() == 200) {

              String accessToken = null;

              String responseText = response.getBody();
              String[] params = responseText.split("&");
              for (String param : params) {
                String[] pair = param.split("=");
                if ("access_token".equals(pair[0])) {
                  accessToken = pair[1];
                  break;
                }
              }

              if (!StringUtils.isBlank(accessToken)) {
                FacebookClient facebookClient = new DefaultFacebookClient(accessToken, webRequestor, new DefaultJsonMapper());
                User facebookUser = facebookClient.fetchObject("me", User.class);
                if (facebookUser != null) {
                  String email = facebookUser.getEmail();
                  if (!StringUtils.isBlank(email)) {
                    String identifier = "facebook." + facebookUser.getId();
                    
                    JSONObject obj = new JSONObject();
                    obj.put("id", identifier);
                    obj.put("email", email);
                    obj.put("firstname", facebookUser.getFirstName());
                    obj.put("lastname", facebookUser.getLastName());

                    getResponse().setEntity(new JsonRepresentation(obj));

                    return getResponse().getEntity();
                    
                  } else {
                    throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Could not get user email");
                  }
                } else {
                  throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Could not find user");
                }

              } else {
                throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Did not get access token");
              }
            } else {
              throw new ResourceException(Status.CLIENT_ERROR_BAD_REQUEST, "Access token verification failed with code " + response.getStatusCode());
            }
          } catch (IOException e) {
            throw new ResourceException(e);
          } catch (JSONException e) {
            throw new ResourceException(e);
          }
        } catch (UnsupportedEncodingException e1) {
          throw new ResourceException(e1);
        }
      }

    } else {

      StringBuilder urlBuilder = new StringBuilder();
      urlBuilder.append("https://www.facebook.com/dialog/oauth?client_id=");
      urlBuilder.append(Settings.getValue(SystemProperty.FACEBOOK_APPID));
      urlBuilder.append("&scope=email");
      urlBuilder.append("&redirect_uri=");
      urlBuilder.append(returnUrlBuilder);

      redirectTemporary(urlBuilder.toString());

      return new EmptyRepresentation();
    }
  }

  private Logger log;
}
